#pragma once
#include "../Common/Common.hpp"
#include "../Common/Log.hpp"
#include "../Index/Index.hpp"
#include "search.pb.h"
#include <jsoncpp/json/json.h>
#include "JsonUtil.hpp"
#include <ctype.h>
using namespace ns_log;
using namespace ns_index;
class Searcher
{
private:
    ns_index::Index *_index;
public:
    Searcher()
    {
    }
    ~Searcher()
    {
    }
    void InitSearch(const std::string &input)
    {
        _index = Index::GetInstance();
        LOG(DEBUG, "获取index单例成功!\n");
        _index->BuildIndex(input);
        LOG(DEBUG, "构建索引成功!\n");
    }
    bool Search(const std::string &input, std::string *out)
    {
        // 1.先分词
        std::vector<std::string> words;
        Util::JiebalUtil::CutFromString(input, &words);
        // 2.触发
        if (words.empty())
        {
            LOG(WARNING, "用户输入的关键字为空!\n");
            return false;
        }
        // 存放所有的倒排拉链
        InvertedList Invertedlist_all;
        for (auto &word : words)
        {
            boost::to_lower(word);
            InvertedList *list = _index->GetInvertedIndex(word);
            if (list == nullptr)
            {
                continue;
            }
            Invertedlist_all.insert(Invertedlist_all.end(), list->begin(), list->end());
        }
        if(Invertedlist_all.empty()) return false;
        // 3.排序
        std::sort(Invertedlist_all.begin(), Invertedlist_all.end(), [&](const InvertedElem &px, const InvertedElem &py)
                  { 
                    return px.weight > py.weight;
                  });

        // 4.构建out
        // protobuf格式序列化
        // search::ElemArray elems;
        // for(auto& e : Invertedlist_all)
        // {
        //     DocInfo * doc = _index->GetForwardIndex(e._id);
        //     if(doc == nullptr) continue;
        //     search::Elem * elem = elems.add_elem_arry();
        //     elem->set_title(doc->_title);
        //     elem->set_desc(GetContentDesc(doc->_content,e.word));//只要content的简介！TODO
        //     elem->set_url(doc->_url);
        // }
        // if(!elems.SerializeToString(out))
        // {
        //     LOG(FATAL,"序列化失败docinfo失败!\n");
        //     return false;
        // }
        // return true;
        //jsoncpp序列化
        Json::Value root;
        for (auto &e : Invertedlist_all)
        {
            DocInfo *doc = _index->GetForwardIndex(e._id);
            if (doc == nullptr)
                continue;
            Json::Value elem;
            elem["title"] = doc->_title;
            elem["desc"] = GetContentDesc(doc->_content, e.word);
            elem["url"] = doc->_url;
            root.append(elem);
        }
        if (!JSONTOOL::JsonTool::Serialization(root, out))
        {
            LOG(FATAL, "序列化失败docinfo失败!\n");
            return false;
        }
        return true;
    }

private:
    std::string GetContentDesc(const std::string &content, const std::string &word)
    {
        //小bug---conetnt中是原本文档，不忽略大小写！
        // 找到第一次出现的word
        const int prev_step = 50;
        const int next_step = 100;
        // // 1. 找到首次出现
        auto iter = std::search(content.begin(), content.end(), word.begin(), word.end(), [](int x, int y)
                                {
                                     return (std::tolower(x) == std::tolower(y));
                                });
        if (iter == content.end())
        {
            return "Not Found!";
        }
        int pos = std::distance(content.begin(), iter);

        // 2. 获取start，end , std::size_t 无符号整数
        int start = 0;
        int end = content.size() - 1;
        // 如果之前有50+字符，就更新开始位置
        if (pos > start + prev_step)
        {
             start = pos - prev_step;
        }
        if (pos < end - next_step)
        {
            end = pos + next_step;
        }

        // 3. 截取子串,return
        std::string desc = content.substr(start, end - start);
        desc += "...";
        return desc;
    }

};